package ink.metoo.gude.module.security.controller

import ink.metoo.gude.aspect.RateLimit
import ink.metoo.gude.model.ApiBody
import ink.metoo.gude.module.security.domain.AuthVerificationCodeConst
import ink.metoo.gude.module.security.domain.dto.LoginDTO
import ink.metoo.gude.module.security.domain.dto.RegisterDTO
import ink.metoo.gude.module.security.domain.dto.RestPasswordDTO
import ink.metoo.gude.module.security.domain.vo.LoginVO
import ink.metoo.gude.module.security.service.AuthService
import ink.metoo.gude.util.ApiUtils
import ink.metoo.gude.util.ApiUtils.toBody
import ink.metoo.gude.util.ApiUtils.toBooleanBody
import jakarta.validation.Valid
import jakarta.validation.constraints.Email
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.*
import java.util.concurrent.TimeUnit

@RestController
@RequestMapping("/auth")
class AuthController(
    private val authService: AuthService
) {

    @RateLimit(max = 3, duration = 1L, timeUnit = TimeUnit.DAYS, key = RateLimit.Key.IP)
    @PreAuthorize("isAnonymous()")
    @PostMapping("/register")
    fun register(@RequestBody @Valid register: RegisterDTO) = ApiUtils.run {
        authService.register(register)
    }

    @PreAuthorize("isAnonymous()")
    @PostMapping("/login")
    fun login(@RequestBody @Valid login: LoginDTO): ApiBody<LoginVO> = ApiUtils.run {
        authService.login(login)
    }

    @GetMapping("/register/check")
    fun checkEmail(@RequestParam("email") @Valid @Email email: String) =
        authService.checkEmail(email).toBody()

    @PreAuthorize("isAnonymous()")
    @GetMapping("/register/verification-code/send")
    fun sendRegisterVerificationCode(@RequestParam("email") @Valid @Email email: String) =
        authService.sendVerificationCode(email, AuthVerificationCodeConst.REGISTER_TYPE, "注册验证码")
            .toBooleanBody()

    @GetMapping("/rest-password/verification-code/send")
    fun sendRestPasswordVerificationCode(@RequestParam("email") @Valid @Email email: String) =
        authService.sendVerificationCode(email, AuthVerificationCodeConst.REST_PASSWORD_TYPE, "修改密码验证码")
            .toBooleanBody()

    @PostMapping("/rest-password")
    fun restPassword(@RequestBody @Valid restPassword: RestPasswordDTO) =
        authService.restPassword(restPassword).toBody()

    @PreAuthorize("isAuthenticated()")
    @GetMapping("/check")
    fun checkLogin() = ApiUtils.success<Unit>()

}